#ifndef __VERTEX_BUFFER_LAYOUT_HPP__
#define __VERTEX_BUFFER_LAYOUT_HPP__

#include "renderer.hpp"
#include <vector>

struct VertexBufferElement {
    unsigned int type;
    unsigned int count;
    unsigned char normalized;
    static unsigned  int GetSizeOfType( unsigned int type ) {
        switch ( type ) {
        case GL_FLOAT: return 4;
        case GL_UNSIGNED_INT: return 4;
        case GL_UNSIGNED_BYTE: return 1;
        }
        ASSERT( false );
        return 0;
    }
};


class VertexBufferLayout
{
    std::vector< VertexBufferElement> _elements;
    unsigned int _stride;
public:
    VertexBufferLayout();
    ~VertexBufferLayout();

    template< typename T>
    void push( unsigned int count ) {
        static_assert( false );
    }

    template<>
    void push<float>( unsigned int count ) {
        _elements.push_back( { GL_FLOAT, count, GL_FALSE } );
        _stride += count * VertexBufferElement::GetSizeOfType( GL_FLOAT );
    }

    template<>
    void push<unsigned int >( unsigned int count ) {
        _elements.push_back( { GL_UNSIGNED_INT, count, GL_TRUE } );
        _stride += count * VertexBufferElement::GetSizeOfType( GL_UNSIGNED_INT );
    }

    template<>
    void push<unsigned char >( unsigned  int count ) {
        _elements.push_back( { GL_UNSIGNED_BYTE, count, GL_FALSE } );
        _stride += count * VertexBufferElement::GetSizeOfType( GL_UNSIGNED_BYTE );
    }

    inline std::vector<VertexBufferElement> getElements() const {
        return std::move(_elements);
    }
    inline unsigned int getStride() const {
        return _stride;
    }
};

#endif // !__VERTEX_BUFFER_LAYOUT_HPP__
